﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AdferInternals
{
    public static class MathHelper
    {
        private static readonly Dictionary<byte, double> ByteToUnitIntervalMap;
        private static readonly Dictionary<byte, double> ByteToSymmetricIntervalMap;

        static MathHelper()
        {
            ByteToUnitIntervalMap = new Dictionary<byte, double>(byte.MaxValue);

            for(byte b = 0; b < byte.MaxValue; ++b)
            {
                ByteToUnitIntervalMap.Add(b, ((double)b) / 256);
            }
            ByteToUnitIntervalMap.Add(255, 255.0 / 256.0);

            ByteToSymmetricIntervalMap = new Dictionary<byte, double>(byte.MaxValue);

            for (byte b = 0; b < byte.MaxValue; ++b)
            {
                ByteToSymmetricIntervalMap.Add(b, ((double)b - 128) / 256);
            }
            ByteToSymmetricIntervalMap.Add(255, (255.0 - 128) / 256.0);
        }

        // (0, 1)
        public static double[][] MapToUnitInterval(byte[][] matrix)
        {
            var result = new double[matrix.Length][];

            for(var i = 0; i < matrix.Length; ++i)
            {
                result[i] = new double[matrix[0].Length];
                for (var j = 0; j < matrix[0].Length; j++)
                {
                    result[i][j] = ByteToUnitIntervalMap[matrix[i][j]];
                }
            }

            return result;
        }

        // (-1, 1)
        public static double[][] MapToSymmetricUnitInterval(byte[][] matrix)
        {
            var result = new double[matrix.Length][];

            for (var i = 0; i < matrix.Length; ++i)
            {
                result[i] = new double[matrix[0].Length];
                for (var j = 0; j < matrix[0].Length; j++)
                {
                    result[i][j] = ByteToSymmetricIntervalMap[matrix[i][j]];
                }
            }

            return result;
        }

        public static string PrintMatrix(double[][] matrix)
        {
            var sb = new StringBuilder(matrix.Length * matrix[0].Length * 10);

            for (var i = 0; i < matrix.Length; i++)
            {
                sb.Append("[");
                for (var j = 0; j < matrix[0].Length; j++)
                {
                    sb.Append(value: Math.Round(matrix[i][j], 2).ToString(CultureInfo.InvariantCulture) + " ");
                }
                sb.Append("]\n");
            }

            return sb.ToString();
        }
    }
}
